// DbUpdate.cpp
#include "DbUpdate.h"
#include <iostream>
#include <sstream>
#include <algorithm> // For std::find_if

// --- 辅助宏或函数 (可选，用于简化错误处理) ---
#define HANDLE_DB_EXCEPTION(try_block, error_msg_var) \
    try { \
        try_block \
    } catch (const std::exception& e) { \
        error_msg_var = "Database update operation failed: "; \
        error_msg_var += e.what(); \
        std::cerr << error_msg_var << std::endl; \
        return false; \
    } catch (...) { \
        error_msg_var = "Database update operation failed: Unknown error occurred."; \
        std::cerr << error_msg_var << std::endl; \
        return false; \
    }

// --- 私有辅助函数实现 ---
std::string DbUpdate::join_repeated_strings(const ::google::protobuf::RepeatedPtrField<std::string>& repeated_field, const std::string& delimiter) {
    std::ostringstream oss;
    bool first = true;
    for (const auto& s : repeated_field) {
        if (!first) oss << delimiter;
        oss << s;
        first = false;
    }
    return oss.str();
}

// --- 更新方法实现 ---

bool DbUpdate::UpdateUser(int32_t user_id, const ::graph::UserNode& user_updates, std::string& error_message) {
    // 构造动态 SET 子句
    std::ostringstream set_clause_oss;

    // --- 构建 SET 子句 ---
    // 总是更新 updated_at 字段
    set_clause_oss << " SET u.updated_at = $updated_at";

    // 更新其他字段 - 对于 string/bool/int，总是更新
    set_clause_oss << ", u.username = $username";
    set_clause_oss << ", u.email = $email";
    set_clause_oss << ", u.password_hash = $password_hash";
    set_clause_oss << ", u.age_group = $age_group";
    set_clause_oss << ", u.gender = $gender";
    set_clause_oss << ", u.location = $location";
    set_clause_oss << ", u.activity_level = $activity_level";

    // 处理 repeated 字段 interests (仅在非空时更新)
    if (user_updates.interests_size() > 0) {
        set_clause_oss << ", u.interests_str = $interests_str";
    }

    const std::string cypher_query =
        "MATCH (u:User {id: $target_id})" +
        set_clause_oss.str() +
        " RETURN u";

    // 构建参数
    std::vector<neo4j_map_entry_t> entries;
    entries.push_back({ .key = neo4j_string("target_id"), .value = neo4j_int(user_id) });
    entries.push_back({ .key = neo4j_string("updated_at"), .value = neo4j_string(user_updates.updated_at().c_str()) });
    entries.push_back({ .key = neo4j_string("username"), .value = neo4j_string(user_updates.username().c_str()) });
    entries.push_back({ .key = neo4j_string("email"), .value = neo4j_string(user_updates.email().c_str()) });
    entries.push_back({ .key = neo4j_string("password_hash"), .value = neo4j_string(user_updates.password_hash().c_str()) });
    entries.push_back({ .key = neo4j_string("age_group"), .value = neo4j_string(user_updates.age_group().c_str()) });
    entries.push_back({ .key = neo4j_string("gender"), .value = neo4j_string(user_updates.gender().c_str()) });
    entries.push_back({ .key = neo4j_string("location"), .value = neo4j_string(user_updates.location().c_str()) });
    entries.push_back({ .key = neo4j_string("activity_level"), .value = neo4j_string(user_updates.activity_level().c_str()) });

    // 处理 repeated 字段 interests
    if (user_updates.interests_size() > 0) {
        std::string interests_str = join_repeated_strings(user_updates.interests());
        entries.push_back({ .key = neo4j_string("interests_str"), .value = neo4j_string(interests_str.c_str()) });
    }

    neo4j_value_t params = neo4j_map(entries.data(), entries.size());

    HANDLE_DB_EXCEPTION(
        {
            DbClient& db_client = DbClient::getInstance();
            neo4j_result_stream_t* result_stream = db_client.run(cypher_query.c_str(), params);
            if (result_stream != nullptr) {
                neo4j_close_results(result_stream);
            }
            std::cout << "Successfully updated User node with ID: " << user_id << std::endl;
        },
        error_message
    )
    return true;
}

bool DbUpdate::UpdateList(int32_t list_id, const ::graph::ListNode& list_updates, std::string& error_message) {
    std::ostringstream set_clause_oss;

    // 总是更新 updated_at 字段
    set_clause_oss << " SET l.updated_at = $updated_at";

    // 更新其他字段
    set_clause_oss << ", l.user_id = $user_id";
    set_clause_oss << ", l.title = $title";
    set_clause_oss << ", l.is_urgent = $is_urgent";
    set_clause_oss << ", l.is_collaborative = $is_collaborative";
    set_clause_oss << ", l.priority = $priority";
    set_clause_oss << ", l.location_scope = $location_scope";
    set_clause_oss << ", l.publish_date = $publish_date";
    set_clause_oss << ", l.start_time = $start_time";
    set_clause_oss << ", l.end_time = $end_time";
    set_clause_oss << ", l.is_public = $is_public";
    set_clause_oss << ", l.view_count = $view_count";
    set_clause_oss << ", l.like_count = $like_count";
    set_clause_oss << ", l.comment_count = $comment_count";
    set_clause_oss << ", l.category = $category";

    // 处理 repeated 字段 tags
    if (list_updates.tags_size() > 0) {
        set_clause_oss << ", l.tags_str = $tags_str";
    }

    const std::string cypher_query =
        "MATCH (l:List {id: $target_id})" +
        set_clause_oss.str() +
        " RETURN l";

    // 构建参数
    std::vector<neo4j_map_entry_t> entries;
    entries.push_back({ .key = neo4j_string("target_id"), .value = neo4j_int(list_id) });
    entries.push_back({ .key = neo4j_string("updated_at"), .value = neo4j_string(list_updates.updated_at().c_str()) });
    entries.push_back({ .key = neo4j_string("user_id"), .value = neo4j_int(list_updates.user_id()) });
    entries.push_back({ .key = neo4j_string("title"), .value = neo4j_string(list_updates.title().c_str()) });
    entries.push_back({ .key = neo4j_string("is_urgent"), .value = neo4j_bool(list_updates.is_urgent()) });
    entries.push_back({ .key = neo4j_string("is_collaborative"), .value = neo4j_bool(list_updates.is_collaborative()) });
    entries.push_back({ .key = neo4j_string("priority"), .value = neo4j_string(list_updates.priority().c_str()) });
    entries.push_back({ .key = neo4j_string("location_scope"), .value = neo4j_string(list_updates.location_scope().c_str()) });
    entries.push_back({ .key = neo4j_string("publish_date"), .value = neo4j_string(list_updates.publish_date().c_str()) });
    entries.push_back({ .key = neo4j_string("start_time"), .value = neo4j_string(list_updates.start_time().c_str()) });
    entries.push_back({ .key = neo4j_string("end_time"), .value = neo4j_string(list_updates.end_time().c_str()) });
    entries.push_back({ .key = neo4j_string("is_public"), .value = neo4j_bool(list_updates.is_public()) });
    entries.push_back({ .key = neo4j_string("view_count"), .value = neo4j_int(list_updates.view_count()) });
    entries.push_back({ .key = neo4j_string("like_count"), .value = neo4j_int(list_updates.like_count()) });
    entries.push_back({ .key = neo4j_string("comment_count"), .value = neo4j_int(list_updates.comment_count()) });
    entries.push_back({ .key = neo4j_string("category"), .value = neo4j_string(list_updates.category().c_str()) });

    // 处理 repeated 字段 tags
    if (list_updates.tags_size() > 0) {
        std::string tags_str = join_repeated_strings(list_updates.tags());
        entries.push_back({ .key = neo4j_string("tags_str"), .value = neo4j_string(tags_str.c_str()) });
    }

    neo4j_value_t params = neo4j_map(entries.data(), entries.size());

    HANDLE_DB_EXCEPTION(
        {
            DbClient& db_client = DbClient::getInstance();
            neo4j_result_stream_t* result_stream = db_client.run(cypher_query.c_str(), params);
            if (result_stream != nullptr) {
                neo4j_close_results(result_stream);
            }
            std::cout << "Successfully updated List node with ID: " << list_id << std::endl;
        },
        error_message
    )
    return true;
}

bool DbUpdate::UpdateTodo(int32_t todo_id, const ::graph::TodoNode& todo_updates, std::string& error_message) {
    std::ostringstream set_clause_oss;

    // 更新其他字段
    set_clause_oss << " SET t.list_id = $list_id";
    set_clause_oss << ", t.content = $content";
    set_clause_oss << ", t.is_completed = $is_completed";
    set_clause_oss << ", t.sort_order = $sort_order";
    set_clause_oss << ", t.category = $category";

    // 处理 repeated 字段 tags
    if (todo_updates.tags_size() > 0) {
        set_clause_oss << ", t.tags_str = $tags_str";
    }

    const std::string cypher_query =
        "MATCH (t:Todo {id: $target_id})" +
        set_clause_oss.str() +
        " RETURN t";

    // 构建参数
    std::vector<neo4j_map_entry_t> entries;
    entries.push_back({ .key = neo4j_string("target_id"), .value = neo4j_int(todo_id) });
    entries.push_back({ .key = neo4j_string("list_id"), .value = neo4j_int(todo_updates.list_id()) });
    entries.push_back({ .key = neo4j_string("content"), .value = neo4j_string(todo_updates.content().c_str()) });
    entries.push_back({ .key = neo4j_string("is_completed"), .value = neo4j_bool(todo_updates.is_completed()) });
    entries.push_back({ .key = neo4j_string("sort_order"), .value = neo4j_int(todo_updates.sort_order()) });
    entries.push_back({ .key = neo4j_string("category"), .value = neo4j_string(todo_updates.category().c_str()) });

    // 处理 repeated 字段 tags
    if (todo_updates.tags_size() > 0) {
        std::string tags_str = join_repeated_strings(todo_updates.tags());
        entries.push_back({ .key = neo4j_string("tags_str"), .value = neo4j_string(tags_str.c_str()) });
    }

    neo4j_value_t params = neo4j_map(entries.data(), entries.size());

    HANDLE_DB_EXCEPTION(
        {
            DbClient& db_client = DbClient::getInstance();
            neo4j_result_stream_t* result_stream = db_client.run(cypher_query.c_str(), params);
            if (result_stream != nullptr) {
                neo4j_close_results(result_stream);
            }
            std::cout << "Successfully updated Todo node with ID: " << todo_id << std::endl;
        },
        error_message
    )
    return true;
}

bool DbUpdate::UpdateComment(int32_t comment_id, const ::graph::CommentNode& comment_updates, std::string& error_message) {
    std::ostringstream set_clause_oss;

    // 更新字段
    set_clause_oss << " SET c.list_id = $list_id";
    set_clause_oss << ", c.user_id = $user_id";
    set_clause_oss << ", c.content = $content";

    const std::string cypher_query =
        "MATCH (c:Comment {id: $target_id})" +
        set_clause_oss.str() +
        " RETURN c";

    // 构建参数
    std::vector<neo4j_map_entry_t> entries;
    entries.push_back({ .key = neo4j_string("target_id"), .value = neo4j_int(comment_id) });
    entries.push_back({ .key = neo4j_string("list_id"), .value = neo4j_int(comment_updates.list_id()) });
    entries.push_back({ .key = neo4j_string("user_id"), .value = neo4j_int(comment_updates.user_id()) });
    entries.push_back({ .key = neo4j_string("content"), .value = neo4j_string(comment_updates.content().c_str()) });

    neo4j_value_t params = neo4j_map(entries.data(), entries.size());

    HANDLE_DB_EXCEPTION(
        {
            DbClient& db_client = DbClient::getInstance();
            neo4j_result_stream_t* result_stream = db_client.run(cypher_query.c_str(), params);
            if (result_stream != nullptr) {
                neo4j_close_results(result_stream);
            }
            std::cout << "Successfully updated Comment node with ID: " << comment_id << std::endl;
        },
        error_message
    )
    return true;
}

bool DbUpdate::UpdateEntity(const std::string& entity_id, const ::graph::EntityNode& entity_updates, std::string& error_message) {
    std::ostringstream set_clause_oss;

    // 更新字段
    set_clause_oss << " SET e.name = $name";
    set_clause_oss << ", e.type = $type";
    set_clause_oss << ", e.category = $category";
    set_clause_oss << ", e.popularity_score = $popularity_score";

    const std::string cypher_query =
        "MATCH (e:Entity {id: $target_id})" +
        set_clause_oss.str() +
        " RETURN e";

    // 构建参数
    std::vector<neo4j_map_entry_t> entries;
    entries.push_back({ .key = neo4j_string("target_id"), .value = neo4j_string(entity_id.c_str()) });
    entries.push_back({ .key = neo4j_string("name"), .value = neo4j_string(entity_updates.name().c_str()) });
    entries.push_back({ .key = neo4j_string("type"), .value = neo4j_string(entity_updates.type().c_str()) });
    entries.push_back({ .key = neo4j_string("category"), .value = neo4j_string(entity_updates.category().c_str()) });
    entries.push_back({ .key = neo4j_string("popularity_score"), .value = neo4j_float(entity_updates.popularity_score()) });

    neo4j_value_t params = neo4j_map(entries.data(), entries.size());

    HANDLE_DB_EXCEPTION(
        {
            DbClient& db_client = DbClient::getInstance();
            neo4j_result_stream_t* result_stream = db_client.run(cypher_query.c_str(), params);
            if (result_stream != nullptr) {
                neo4j_close_results(result_stream);
            }
            std::cout << "Successfully updated Entity node with ID: " << entity_id << std::endl;
        },
        error_message
    )
    return true;
}